﻿
namespace TestFsWeb

open System
open System.Net
open System.IO
open System.Threading
open Microsoft.FSharp.Control.WebExtensions

open Helper
open TestFsWeb.HttpListenerExtend

type ChatWebServer(m_url,m_rootDir)=
    // *********************** primary constructor
    let m_chatAgent = new ChatRoomAgent()

    let m_contentTypes = dict [".css","text/css";".html","text/html";".js","text/javascript"]

    let handleRequest(ctx: HttpListenerContext) = async {
        match ctx.Request.Url.LocalPath with
        | "/append" -> 
            let! msg = ctx.Request.AsyncInputString
            m_chatAgent.Send msg
            do! ctx.Response.AsyncReply "OK"
        | "/gethistory" -> 
            let! history = m_chatAgent.AsyncGet()
            do! ctx.Response.AsyncReply history
        | fileName -> 
            // chekanote: pay attention that, we cannot use Path.Combine here
            // even we are just concatenating path to files
            // because 'LocalPath' starts with "\" or "/"
            // which exceed the capacity of Path.Combine
            let wholePath = 
                if fileName.Equals("/") then "index.html" else fileName
                |> combine_path m_rootDir 

            if File.Exists wholePath then
                let ext = Path.GetExtension(wholePath).ToLower()
                let contType = m_contentTypes.[ext]
                let contents = File.ReadAllBytes wholePath // short files, sync-read is sufficient
                do! ctx.Response.AsyncReply(contType,contents)
            else
                let errMsg = sprintf "File Not Found: %s" wholePath
                do! ctx.Response.AsyncReply errMsg
                printfn "%s" errMsg
    }

    let m_svrAgent = HttpSvrAgent.Start(m_url,
                                        fun inbox -> async {
                                            while true do
                                                let! ctx = inbox.Receive()
                                                ctx 
                                                |> handleRequest 
                                                |> Async.Start
                                        })

    // *********************** members
    interface IDisposable with
        member this.Dispose() =
            (m_chatAgent :> IDisposable).Dispose()
            m_svrAgent.Stop()
            (m_svrAgent :> IDisposable).Dispose()

module TestChatWebServer =
    let main() =
        use server = new ChatWebServer("http://localhost:8082/",@"D:\Study\programming\DotNet\LearnByTest\FSharp\TestFsWeb\ChatServer\")
        printfn "chat web server is running, ......"

        pause_for("exit")
